package com.banban.user.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.banban.user.service.AliyunOssService;
import com.banban.user.util.UniqueIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@Service
@Slf4j
public class AliyunOssServiceImpl implements AliyunOssService {

    @Autowired
    private OSS ossClient;

    @Value("${oss.Endpoint}")
    private String endPoint;

    @Value("${oss.Bucket}")
    private String Bucket;

    @Value("${oss.APIKey}")
    private String accessKeyId;
    @Value("${oss.APISecret}")
    private String accessKeySecret;

    /**
     * 创建bucket
     */
    @Override
    public void createBucket(String bucketName){
        try {
            // 创建存储空间。
            Bucket bucket = ossClient.createBucket(bucketName);
            log.info("bucket创建成功, bucketName = {}",  bucket.getName());
        } catch (Exception e) {
            System.out.println("Error Message:" + e.getMessage());
        }
    }


    /**
     * 上传文件
     */
    @Override
    public String uploadFile(String bucketName, String objectName, InputStream inputStream){
        String url = "";
        try {
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);
            url = generatePresignedUrl(ossClient, bucketName, objectName, 60 * 60 * 24 * 365 * 10);
            log.info("oss文件上传  bucketName = {} putObjectResult = {}, url = {}", bucketName, putObjectResult, url);
        } catch (Exception e) {
            log.error("oss Error Message:" + e.getMessage());
        }
        return url;
    }

    @Override
    public String uploadFileWithSuffix(String bucketName, String objectName, String suffix, InputStream inputStream) {
        String url = "";
        objectName = objectName + UniqueIDUtil.generateId() + suffix;
        try {
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);
            url = generatePresignedUrl(ossClient, bucketName, objectName, 60 * 60 * 24 * 365 * 10);
            log.info("oss文件上传  bucketName = {} putObjectResult = {}, url = {}", bucketName, putObjectResult, url);
        } catch (Exception e) {
            log.error("oss Error Message:" + e.getMessage());
        }
        return url;
    }

    public String generatePresignedUrl(OSS ossClient, String bucketName, String objectKey, long expirationInSeconds) {
        String url = "";
        try {
            // 创建签名URL请求
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
            request.setExpiration(new Date(System.currentTimeMillis() + expirationInSeconds * 1000));

            // 生成签名URL
            URL signedUrl = ossClient.generatePresignedUrl(request);
            url = signedUrl.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

//    /**
//     * 下载文件
//     */
//    public void  downloadFile(){
//        // 填写Bucket名称
//        String bucketName = "java-hello-world";
//        // 填写Object完整路径，需要包含文件名，但不用包含Bucket名称
//        String objectName = "test/test.txt";
//
//        try {
//            // 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
//            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
//
//            // 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
//            InputStream content = ossObject.getObjectContent();
//
//            if (content != null) {
//                BufferedReader reader = new BufferedReader(new InputStreamReader(content));
//                while (true) {
//                    String line = reader.readLine();
//                    if (line == null) {
//                        break;
//                    }
//                    System.out.println("\n" + line);
//                }
//                // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
//                content.close();
//            }
//        } catch (Exception e) {
//            System.out.println("Error Message:" + e.getMessage());
//        } finally {
//            if (ossClient != null) {
//                ossClient.shutdown();
//            }
//        }
//    }


    /**
     * 从OSS下载文件并返回给HTTP响应
     * @param response
     * @param path
     * @param fileName
     */
    @Override
    public void download(HttpServletResponse response, String path, String fileName) throws UnsupportedEncodingException {
//        String path = "resource/staticResource/";
//        String fileName= "19928014779049260%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%BA%94%E7%94%A8%E6%94%AF%E6%92%91%E8%83%BD%E5%8A%9B%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3.docx";
        // 创建OSSClient实例
        fileName = URLDecoder.decode(fileName, StandardCharsets.ISO_8859_1.name());
        fileName = new String(fileName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);

        // 调用OSSClient下载文件并写入到response的输出流中
        OSSObject ossObject = ossClient.getObject(Bucket, path+fileName);

        try (InputStream fis = ossObject.getObjectContent(); OutputStream fos = response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            // 设置HTTP头信息，解决文件名中文乱码问题
            response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while((bytesRead = fis.read(buffer, 0, 1024)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush();
        } catch (Exception e){
            log.error("OssClient–>download throw Exception.name:{},path:{}", fileName, path, e);
        }
        ossClient.shutdown();

    }
}
